import { OnInit, Component, ViewChild, ElementRef, Inject } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { AppStoreModule } from 'src/app/store/store.module';
import {
  getPlayList, getPlayer,
  getSongList, getCurrentIndex,
  getPlayMode, getCurrentSong
} from 'src/app/store/selector/play.selector';
import { Song } from 'src/app/routes/entity';
import { PlayMode } from 'src/app/store/entity';
import { setCurrentIndex, setPlayMode, setPlayList, setSongList } from 'src/app/store/actions/play.actions';
import { DOCUMENT } from '@angular/common';
import { shuffleList } from 'src/app/util/array.util';
import { MusicPlayPanelComponent } from '../music-play-panel/music-play-panel.component';
import { Router } from '@angular/router';

@Component({
  selector: 'app-music-play',
  templateUrl: './music-play.component.html',
  styleUrls: ['./music-play.component.less']
})
export class MusicPlayComponent implements OnInit {
  /** 音乐播放进度 */
  playLength = 0;
  /** 音乐缓冲进度 */
  bufferLength = 0;

  playList: Song[] = [];
  songList: Song[] = [];
  currentIndex: number;
  currentSong: Song;
  playMode: PlayMode;

  @ViewChild('audio', { static: true })
  private audio: ElementRef;
  private audioElem: HTMLAudioElement;
  audioDuration: number;
  audioCurrentTime: number;

  /** 音乐播放状态 */
  isPlaying = false;
  /** 是否可以播放，当音乐资源已经获取到时，表示可以播放 */
  isCanPlay = false;

  /** 音量，默认 60 */
  volume = 60;
  /** 是否显示音量进度条 */
  isShowVolumeSlider = false;
  /** 是否显示音乐列表面板 */
  isShowPlayPanel = false;
  /** 是否是点击播放面板本身 */
  isBindClick = false;

  /** 播放模式 */
  private playModes: PlayMode[];
  private modeClickCount = 0;

  @ViewChild(MusicPlayPanelComponent, { static: false })
  private playPanel: MusicPlayPanelComponent;

  constructor(
    private store$: Store<AppStoreModule>,
    private router: Router,
  ) {
    this.watchPlayerStateStore();
  }

  ngOnInit(): void {
    this.audioElem = this.audio.nativeElement;
    this.playModes = [
      { type: 'singleLoop', label: '单曲循环' },
      { type: 'loop', label: '循环' },
      { type: 'random', label: '随机' }
    ];
    // 获取初始 playMode 的索引
    this.modeClickCount = this.playModes.findIndex(e => this.playMode.type == e.type);
  }

  onAudioTimeUpdate(event: Event) {
    this.audioCurrentTime = (event.target as HTMLAudioElement).currentTime;
    // 计算播放进度
    this.playLength = (this.audioCurrentTime / this.audioDuration) * 100;
    // 计算缓冲进度
    const buffered = this.audioElem.buffered;
    if (buffered.length && this.playLength < 100) {
      this.bufferLength = (buffered.end(0) / this.audioDuration) * 100;
    }
  }

  /** 音乐开关事件 */
  onToggle(): void {
    // 当前播放音乐索引不存在，但播放列表存在，则重新指定当前播放音乐索引
    if (!this.currentSong) {
      if (this.playList.length) {
        this.updateIndex(0);
      }
      return;
    }
    // 音乐能播放
    if (this.isCanPlay) {
      this.isPlaying = !this.isPlaying;
      if (this.isPlaying) {
        this.playMusic();
        return;
      }
      this.pauseMusic();
    }
  }

  /** 上一首 */
  onPrev(index: number): void {
    if (!this.isCanPlay) {
      return;
    }
    if (this.playList.length === 1) {
      this.singleLoop();
    }
    const newIndex = index < 0 ? this.playList.length - 1 : index;
    this.updateIndex(newIndex);
  }

  /** 下一首 */
  onNext(index: number): void {
    if (!this.isCanPlay) {
      return;
    }
    if (this.playList.length === 1) {
      this.singleLoop();
    }
    const newIndex = index >= this.playList.length ? 0 : index;
    this.updateIndex(newIndex);
  }

  routerToSongDetail(songId: string): void {
    if (!songId) {
      return;
    }
    this.isShowPlayPanel = false;
    this.isShowVolumeSlider = false;
    this.router.navigateByUrl(`/music/songs/${songId}/detail`);
  }

  onChangeCurrentSongEvent(song: Song): void {
    this.updateCurrentIndex(this.playList, song);
  }

  /** 播放进度条长度比变更事件 */
  onPlayLengthChangeEvent(percent: number): void {
    if (this.currentSong) {
      const toggleTime = this.audioDuration * (percent / 100);
      this.audioElem.currentTime = toggleTime;
      if (this.playPanel) {
        this.playPanel.skipLyric(toggleTime * 1000);
      }
    }
  }

  /** 音量变更事件 */
  onVolumeChangeEvent(volume: number): void {
    this.audioElem.volume = volume / 100;
  }

  /** 音量控制条显示事件 */
  onShowVolumeSliderEvent(): void {
    this.onShowComponent('isShowVolumeSlider');
  }

  /** 音乐列表面板显示事件 */
  onShowPlayPanelEvent(): void {
    this.onShowComponent('isShowPlayPanel');
  }

  /** 音乐播放事件，当音乐可以播放时，触发该事件 */
  onCanPlay(): void {
    this.isCanPlay = true;
    this.playMusic();
  }

  /** 歌曲播放结束 */
  onEnded(): void {
    this.isPlaying = false;
    // 单曲循环
    if (this.playMode.type === 'singleLoop') {
      this.singleLoop();
    } else {
      // 下一首
      this.onNext(this.currentIndex + 1);
    }
  }

  onChangeModeEvent(): void {
    const mode = this.playModes[++this.modeClickCount % 3];
    this.store$.dispatch(setPlayMode({ playMode: mode }));
    // 当所有模式循环一轮后，将modeClickCount清零
    if (this.modeClickCount >= 3) {
      this.modeClickCount = 0;
    }
  }

  /** 删除单个歌单 */
  onDeleteSongEvent(songId: number): void {
    this.isShowPlayPanel = true;
    this.isShowVolumeSlider = true;
    const songListTemp = this.songList.slice();
    const playListTemp = this.playList.slice();
    let currentIndexTemp = this.currentIndex;
    const sIndex = this.songList.findIndex(e => e.id === songId);
    songListTemp.splice(sIndex, 1);
    const pIndex = this.playList.findIndex(e => e.id === songId);
    playListTemp.splice(pIndex, 1);
    if (currentIndexTemp > pIndex || currentIndexTemp === playListTemp.length) {
      currentIndexTemp--;
    }
    this.store$.dispatch(setSongList({ songList: songListTemp }));
    this.store$.dispatch(setPlayList({ playList: playListTemp }));
    this.store$.dispatch(setCurrentIndex({ currentIndex: currentIndexTemp }));
  }

  /** 清空歌单列表 */
  onClearSongListEvent(): void {
    this.store$.dispatch(setSongList({ songList: [] }));
    this.store$.dispatch(setPlayList({ playList: [] }));
    this.store$.dispatch(setCurrentIndex({ currentIndex: -1 }));
  }

  onClickOutsideEvent(): void {
    // 隐藏音量控制条
    this.isShowVolumeSlider = false;
    // 隐藏音乐列表面板
    this.isShowPlayPanel = false;
    this.isBindClick = false;
  }

  private onShowComponent(type: string): void {
    this[type] = !this[type];
    this.isBindClick = this.isShowPlayPanel || this.isShowVolumeSlider;
  }

  private playMusic(): void {
    this.audioElem.play();
    this.isPlaying = true;
  }

  private pauseMusic(): void {
    this.audioElem.pause();
  }

  /** 单曲循环 */
  private singleLoop(): void {
    this.audioElem.currentTime = 0;
    this.playMusic();
    if (this.playPanel) {
      this.playPanel.skipLyric(0);
    }
  }

  private watchPlayerStateStore(): void {
    const playerStore$ = this.store$.pipe(select(getPlayer));
    playerStore$.pipe(select(getPlayList)).subscribe(list => {
      this.watchList('playList', list);
    });

    playerStore$.pipe(select(getSongList)).subscribe(list => {
      this.watchList('songList', list);
    });

    playerStore$.pipe(select(getPlayMode)).subscribe(mode => {
      this.watchPlayMode(mode);
    });

    playerStore$.pipe(select(getCurrentIndex)).subscribe(index => {
      this.watchCurrentIndex(index);
    });

    playerStore$.pipe(select(getCurrentSong)).subscribe(song => {
      this.watchCurrentSong(song);
    });
  }

  private watchList(type: string, list: Song[]): void {
    this[type] = list;
  }

  private watchPlayMode(mode: PlayMode): void {
    this.playMode = mode;
    if (this.songList) {
      let list = this.songList.slice();
      if (this.playMode.type === 'random') {
        // 打乱歌曲顺序
        list = shuffleList(this.songList);
      }
      // 更新当前播放歌单
      this.updateCurrentIndex(list, this.currentSong);
      // 更新播放列表
      this.store$.dispatch(setPlayList({ playList: list }));
    }
  }

  /** 更新当前播放音乐索引 */
  private updateCurrentIndex(playList: Song[], song: Song): void {
    const newIndex = playList.findIndex(e => e.id === song.id);
    this.store$.dispatch(setCurrentIndex({ currentIndex: newIndex }));
  }

  /** 更新播放音乐的索引 */
  private updateIndex(index: number): void {
    this.store$.dispatch(setCurrentIndex({ currentIndex: index }));
    this.isCanPlay = false;
  }

  private watchCurrentIndex(index: number): void {
    this.currentIndex = index;
  }

  private watchCurrentSong(song: Song): void {
    if (song) {
      this.currentSong = song;
      this.audioDuration = song.dt / 1000;
    }
  }

  /** 获取音乐图片链接 */
  get picUrl(): string {
    const defaultPicUrl = 'http://s4.music.126.net/style/web2/img/default/default_album.jpg';
    return this.currentSong ? this.currentSong.al.picUrl : defaultPicUrl;
  }

}
